package xyz.xiezc.spider.common.annotation;

import lombok.Data;
import xyz.xiezc.spider.common.BaseDO;

import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 爬取的实例信息的描述类
 *
 * @author wb-xzc291800
 * @date 2019/04/04 16:31
 */
@Data
public class InstanceDefine {

    /**
     * 这个bean可匹配的url集合
     */
    List<Pattern> patterns = new ArrayList<>();

    /**
     * 正则匹配的字段
     */
    List<String> queryParam;

    Class aClass;

    MatchBean matchBean;

    /**
     * 每个字段的注解
     */
    Map<Field, MatchField> matchFieldMap = new HashMap<>();

    /**
     * 每个字段的注解
     */
    Map<Field, NextRequest> nextRequestMap = new HashMap<>();
    /**
     * 正则匹配url中的信息
     */
    Map<Pattern, Field> queryParamMap = new HashMap<>();

    /**
     * 正则匹配url中的信息
     */
    Map<Integer, Field> queryIndexMap = new HashMap<>();

    public InstanceDefine(Class aClass, MatchBean matchBean) {
        this.aClass = aClass;
        this.matchBean = matchBean;
        this.init();
    }

    /**
     * 匹配url, 判断这个url是否与此类对应的bean关联,
     * 关联则生成bean,同时解析url设置值后返回
     * 不关联则返回null
     *
     * @param urlStr
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public BaseDO getByUrlStr(String urlStr) throws IllegalAccessException, InstantiationException {
        for (Pattern pattern : patterns) {
            Matcher matcher = pattern.matcher(urlStr);
            if (matcher.matches()) {
                //注入根据index的字段
                BaseDO obj = (BaseDO) aClass.newInstance();
                int groupCount = matcher.groupCount();
                for (int i = 0; i < groupCount; i++) {
                    Field field = this.queryIndexMap.get(i + 1);
                    if (field == null) {
                        continue;
                    }
                    String group = matcher.group(i + 1);
                    if (!field.isAccessible()) {
                        field.setAccessible(true);
                    }
                    field.set(obj, group);
                }
                //注入根据正则的字段
                Set<Map.Entry<Pattern, Field>> entries = this.queryParamMap.entrySet();
                for (Map.Entry<Pattern, Field> entry : entries) {
                    Field value = entry.getValue();
                    Pattern key = entry.getKey();
                    Matcher matcher1 = key.matcher(urlStr);
                    while (matcher1.find()) {
                        String group = matcher1.group();
                        if (!value.isAccessible()) {
                            value.setAccessible(true);
                        }
                        value.set(obj, group);
                    }
                }
                return obj;
            }
        }
        return null;
    }

    private void init() {
        Field[] declaredFields = aClass.getDeclaredFields();
        //处理每个字段
        for (Field field : declaredFields) {
            MatchField matchField = field.getAnnotation(MatchField.class);
            if (matchField != null) {
                this.matchFieldMap.put(field, matchField);
            }
            NextRequest nextRequest = field.getAnnotation(NextRequest.class);
            if (nextRequest != null) {
                this.nextRequestMap.put(field, nextRequest);
            }
            //从url中获取信息的注解
            QueryParam queryParam = field.getAnnotation(QueryParam.class);
            if (queryParam != null) {
                int index = queryParam.index();
                if (index > 0) {
                    this.queryIndexMap.put(index, field);
                } else {
                    String value = queryParam.value();
                    this.queryParamMap.put(Pattern.compile(value), field);
                }
            }
        }

        String[] value = matchBean.value();
        for (String val : value) {
            patterns.add(Pattern.compile(val));
        }
    }


}
